using Microsoft.EntityFrameworkCore;

using Volo.Abp.Domain.Entities;
using Volo.Abp.EntityFrameworkCore;
using WL.Think.Abp.Entities;
using WL.Think.Abp.EntityFrameworkCore;

namespace WL.Think.Abp.Repositories;

/// <summary>
/// 分类基础仓储
/// </summary>
/// <typeparam name="TCategory"></typeparam>
public abstract class BaseCategoryRepository<TDbContext, TCategory, TKey> : EfCoreKeyRepository<TDbContext, TCategory, TKey>,IBaseCategoryRepository<TCategory, TKey>
    where TCategory : BaseCategory<TCategory, TKey>,IEntity<TKey>
    where TDbContext : AppDbContextBase<TDbContext>
    where TKey: struct, IComparable<TKey>
{

    protected BaseCategoryRepository(IDbContextProvider<TDbContext> dbContextProvider) : base(dbContextProvider)
    {
       
    }

    public override async Task<IQueryable<TCategory>> WithDetailsAsync()
    {
        var queryable = await base.WithDetailsAsync();
        queryable = queryable.Include(s => s.Children).OrderBy(s => s.Index);
        return queryable;
    }


    public async Task<List<TCategory>> GetTreeAsync(TKey? parentId = null, CancellationToken cancellationToken = default)
    {
        var items = await GetListAsync(x => x.IsActive, true, cancellationToken);
        if (items.Count > 0)
        {
            items = items.Where(s => s.ParentId == null).ToList();
        }
        return await FilterListAsync(items ?? [], parentId, cancellationToken);
    }

    public async Task<List<TCategory>> GetActiveTreeAsync(TKey? parentId = null, CancellationToken cancellationToken = default)
    {
        var queryale = await WithDetailsAsync();
        var list = await queryale.Where(x => x.IsActive).ToListAsync();
        return await FilterListAsync(list ?? [], parentId, cancellationToken);
    }

    public async Task<int> GetMaxIndexAsync(TKey parentId)
    {
        var queryable = await GetQueryableAsync();
        return await queryable.Where(x => x.ParentId.Equals(parentId)).MaxAsync(x => (int?)x.Index) ?? 0;
    }


    /// <summary>
    /// 过滤处符合条件的分类列表
    /// </summary>
    /// <param name="list"></param>
    /// <param name="parentId"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    protected virtual async Task<List<TCategory>> FilterListAsync(IList<TCategory> list, TKey? parentId = null, CancellationToken cancellationToken = default)
    {
        if (list.Count == 0)
        {
            return [];
        }

        if (parentId != null)
        {
            IList<TCategory> items = [.. list.Where(s => s.Id.Equals(parentId))];
            if (items.Count <= 0)
            {
                list = [.. list.SelectMany(s => s.Children!)];
                items = await FilterListAsync(list, parentId, cancellationToken);
            }
            list = items;
        }
        else
        {
            list = [.. list.Where(s => s.ParentId == null)];
        }

        return list.ToList();
    }
}


public abstract class BaseCategoryRepository<TDbContext, TCategory> : 
    BaseCategoryRepository<TDbContext, TCategory, Guid>,
    IBaseCategoryRepository<TCategory>
    where TCategory : BaseCategory<TCategory, Guid>
    where TDbContext : AppDbContextBase<TDbContext>
{
    protected BaseCategoryRepository(IDbContextProvider<TDbContext> dbContextProvider) : base(dbContextProvider)
    {
    }
}
